<?php

    #-------------------------------------------------------------#
	# This file is part of the Tekuna MVC Microframework for PHP. #
	# (c) 2009 Niels Jäckel <niels.jaeckel@tekuna.org>            #
	# Please visit http://tekuna.org/ for more information.       #
	#                                                             #
	# This software is licensed under the MIT License. Please     #
	# view the LICENSE file for the full text of this license.    #
    #-------------------------------------------------------------#


	Tekuna :: load('org.tekuna.core.mvc.view.AbstractView');
	Tekuna :: load('org.tekuna.core.mvc.view.TemplateNotFoundException');


	/**
	 * TekunaView implementation that uses plain PHP files as templates. The
	 * assigned values are available as regular PHP variables within the used template.
	 */

	class PHPView extends AbstractView {


		/**
		 * Use this special method to assign array template variables to
		 * be accessed as PHP objects. That means, that you do not have
		 * to access associative arrays like this:
		 *
		 *    $myArray['myKey']
		 *
		 * but like this:
		 *
		 *    $myArray -> myKey
		 *
		 * Each array will be converted to an object of the PHP stdClass
		 * class that holds the keys and values of the array as attributes
		 * and attribute values. If a key of the array is no possible PHP
		 * identifier, a IllegalArgumentException is thrown.
		 *
		 * @param string $sVar the variable name
		 * @param array $mValue the array
		 */

		public function assignArrayAsObjectTree($sVar, array $mValue) {

	    	$this -> assign($sVar, $this -> arrayToObjectTree($mValue));
		}


        protected function arrayToObjectTree(array $arrValues) {

            // make new instance of PHP standard class
            $objReturn = new stdClass();

            foreach ($arrValues as $sAttr => $sVal) {

                // if invalid key (numeric array) return array as it is
                // REGEX from PHP manual (describes valid varname)
                if (! preg_match('~^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$~', $sAttr)) {

					throw new InvalidArgumentException("The given key name does not satisfy PHPs naming convention for variables. Please replace the key '$sAttr' with something that can be used as variable name. Possible cause for this problem: numeric array indices. Solution: make this array associative.");
                }

				// assign strings, ints, floats directly and all other recursively
				if (is_scalar($sVal) || is_null($sVal)) {

                    $objReturn -> $sAttr = $sVal;
				}
				else {

                    $objReturn -> $sAttr = $this -> arrayToObjectTree($sVal);
				}
            }

            return $objReturn;
        }


		/**
		 * Processes the PHPView template engine. If the template file does
		 * not exist or is not readable, a TemplateNotFoundException is thrown.
		 *
		 * @return string the output
		 */

	    public function process() {

			// compose template file path
			$sTemplateFile = $this -> getTemplateBaseDir() . $this -> getTemplate();

	    	// check if template existent and readable
	    	if (! file_exists($sTemplateFile) || ! is_readable($sTemplateFile)) {

	    		throw new TemplateNotFoundException("The template file '$sTemplateFile' does not exist or is not readable.");
	    	}

	    	// assign all variables in this scope
	    	foreach ($this -> getAllValues() as $sVariable => $sValue) {

	    		$$sVariable = $sValue;
	    	}

	    	// include template
	    	ob_start();
	    	include($sTemplateFile);
	    	$sOutput = ob_get_contents();
	    	ob_end_clean();

	    	// return buffered output
	    	return $sOutput;
	    }
	}

